using System;
using System.Globalization;
using System.Resources;
using System.Text.RegularExpressions;
using System.Threading;
using System.Web;
using System.Xml;
using System.Xml.Serialization;
using Microsoft.SharePoint.Utilities;

namespace DE.Sdc.SharePoint.Common.Deployment
{
    [Serializable]
    public abstract class NamedElement<TParent> : NamedElement where TParent : NamedElement
    {
        private string _path;

        public TParent Parent { get; set; }

        [XmlAttribute]
        public override string Path
        {
            get
            {
                if (!string.IsNullOrEmpty(_path) || GetType() == typeof(ContentStructure))
                    return _path;

                if (Parent != null)
                    return Parent.Path + @"\" + Title;

                throw new ArgumentNullException("No path specified for '" + Title + "'");
            }
            set
            {
                _path = value;
            }
        }
    }

    [Serializable]
    public abstract class NamedElement
    {
        /// <remarks/>
        [XmlAttribute]
        public string Title { get; set; }

        [XmlAttribute]
        public virtual string Path { get; set; }

        /// <remarks/>
        [XmlAttribute]
        public ActionType Action { get; set; }

        public static string ResolveResource(string input, CultureInfo culture)
        {
            if (string.IsNullOrEmpty(input))
                return input;

            Thread.CurrentThread.CurrentUICulture = culture;
            Regex regex = new Regex(@"\$.*?\;", RegexOptions.Multiline);
            return regex.Replace(input, new MatchEvaluator(ResolveResource));
        }

        private static string ResolveResource(Match match)
        {
            try
            {
                Regex regex = new Regex(@"(?<=\$Resources:).*?(?=\;)", RegexOptions.Multiline | RegexOptions.IgnoreCase);
                // $Resource:ClassKey,ResourceKey; --> excludes $Resources; leaves ClassKey,ResourceKey
                Match resourceMatch = regex.Match(match.Value);
                var resourceFields = System.Web.Compilation.ResourceExpressionBuilder.ParseExpression(resourceMatch.Value);
                string resourceValue = null;

                if (resourceFields != null)
                {
                    try
                    {
                        resourceValue =
                            HttpContext.GetGlobalResourceObject(resourceFields.ClassKey, resourceFields.ResourceKey,
                                                                Thread.CurrentThread.CurrentUICulture) as string;
                    }
                    catch
                    {
                        string resourceDir = SPUtility.GetGenericSetupPath("Resources");
                            //System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles),
                            //                       @"Microsoft Shared\web server extensions\12\Resources");

                        try
                        {
                            ResourceManager resourceManager = new ResxResourceManager(resourceFields.ClassKey,
                                                                                      resourceDir);
                            //ResourceManager.CreateFileBasedResourceManager(resourceFields.ClassKey, resourceDir,
                            //                                               null);
                            resourceValue = resourceManager.GetString(resourceFields.ResourceKey);
                        }
                        catch (Exception)
                        {
                            string resourceFile = System.IO.Path.Combine(resourceDir,
                                                                         resourceFields.ClassKey + "." +
                                                                         Thread.CurrentThread.CurrentUICulture.Name + ".resx");

                            if (!System.IO.File.Exists(resourceFile))
                            {
                                resourceFile = System.IO.Path.Combine(resourceDir,
                                                                      resourceFields.ClassKey + ".resx");
                            }

                            XmlDocument resourceDocument = new XmlDocument();
                            resourceDocument.Load(resourceFile);

                            if (resourceDocument.DocumentElement != null)
                            {
                                XmlNode resourceNode =
                                    resourceDocument.DocumentElement.SelectSingleNode("//Data/Value [../@Name='" +
                                                                                      resourceFields.ResourceKey +
                                                                                      "'] | //data/value [../@name='" +
                                                                                      resourceFields.ResourceKey +
                                                                                      "']");

                                resourceValue = resourceNode.InnerText;
                            }
                        }
                    }
                }

                if (string.IsNullOrEmpty(resourceValue) && resourceFields != null && resourceFields.ResourceKey == "Culture")
                    resourceValue = Thread.CurrentThread.CurrentUICulture.Name;

                return resourceValue;
            }
            catch (Exception ex)
            {
                throw new ArgumentException("Error while reading the resource " + match.Value, ex);
            }
        }

        /// <summary>
        /// Delivers a string with the absolute feature related path to a given filename within the feature
        /// </summary>
        /// <param name="file">A filename from a file within the feature</param>
        /// <returns>A string with the absolute path</returns>
        protected static internal string GetFeatureRootedPath(string file)
        {
            if (System.IO.Path.IsPathRooted(file))
                return file;

            return System.IO.Path.Combine(ContentStructureImporter.ReceiverProperties.Definition.RootDirectory, file);
        }
    }
}